package app.blog.entity;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import slap.berkeleydb.BDB;
import slap.paradigm.Function;

import app.blog.Blog;

import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.SecondaryIndex;
import com.sleepycat.persist.model.DeleteAction;
import com.sleepycat.persist.model.Entity;
import com.sleepycat.persist.model.PrimaryKey;
import com.sleepycat.persist.model.Relationship;
import com.sleepycat.persist.model.SecondaryKey;


@Entity
public class Category {
	
	protected static PrimaryIndex<Integer, Category> primaryIndex = 
		BDB.instanse(Blog.bdbName).getEntityStore().getPrimaryIndex(Integer.class, Category.class);
	
	protected static SecondaryIndex<String, Integer, Category> indexOnName = 
		BDB.instanse(Blog.bdbName).getEntityStore().getSecondaryIndex(primaryIndex, String.class, "name");
	
	protected static SecondaryIndex<String, Integer, Category> indexOnSlug = 
		BDB.instanse(Blog.bdbName).getEntityStore().getSecondaryIndex(primaryIndex, String.class, "slug");
	
	protected static SecondaryIndex<Integer, Integer, Category> indexOnParent = 
		BDB.instanse(Blog.bdbName).getEntityStore().getSecondaryIndex(primaryIndex, Integer.class, "parentId");
	
	public static List<Category> all() {
		return BDB.asList(primaryIndex);
	}
	
	public static List<Category> roots() {
		final List<Category> roots = new ArrayList<Category>();
		BDB.traverse(primaryIndex.entities(), new Function<Void, Category>(){
			@Override
			public Void invoke(Category cat) {
				if(cat.parentId==null || cat.parentId==0){
					roots.add(cat);
				}
				return null;
			}
		});
		
		return roots;
	}
	
	public static Category getById(Integer id){
		return primaryIndex.get(id);
	}
	
	public static Category getByName(String name){
		return indexOnName.get(name);
	}
	
	public static Category getBySlug(String slug){
		return indexOnSlug.get(slug);
	}
	
	public static void persist(Category category){
		primaryIndex.put(category);
	}
	
	@PrimaryKey(sequence = "cat-id")
	public Integer id;
	
	@SecondaryKey(relate = Relationship.ONE_TO_ONE)
	public String name;
	
	@SecondaryKey(relate = Relationship.ONE_TO_ONE)
	public String slug;
	
	@SecondaryKey(
			relate = Relationship.MANY_TO_ONE, 
			relatedEntity = Category.class, 
			onRelatedEntityDelete = DeleteAction.NULLIFY
	)
	public Integer parentId;
	
	public Category parent(){
		if(parentId == null){
			return null;
		}
		return primaryIndex.get(parentId);
	}
	
	public List<Category> children(){
		final List<Category> children = new ArrayList<Category>();
		EntityCursor<Category> cursor = indexOnParent.subIndex(this.id).entities();
		try{
			for(Category cat : cursor){
				children.add(cat);
			}
		}finally{
			cursor.close();
		}
		
		return children;
	}

}
